package com.lxw.myeverything.controller;

import com.lxw.myeverything.entity.FileMatchCondition;
import com.lxw.myeverything.entity.MyResponse;
import com.lxw.myeverything.entity.StringMatchCondition;
import com.lxw.myeverything.utils.FileUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.File;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@RestController
public class QueryController {
    private static final List<String> TEXT_FILE = Arrays.asList("txt", "doc", "docx", "xls", "xlsx", "java", "properties", "json", "log", "xml", "vue", "html", "js", "css","md");

    @RequestMapping("/query")
    public Object query(@RequestBody FileMatchCondition fileMatchCondition) throws ParseException, IOException {
        long start = System.currentTimeMillis();
        String directories = fileMatchCondition.getDirectories();
        if (StringUtils.isEmpty(directories)) {
            return MyResponse.failure().setMessage("温馨提示:文件夹不能为空");
        }
        List<File> allFiles = getAllFiles(directories);
        List<String> list = new ArrayList<>();
        for (File file : allFiles) {
            // 根据类型过滤 只有类型有内容才进行类型判断 短路操作
            String fileType = fileMatchCondition.getFileType();
            if (!StringUtils.isEmpty(fileType) && !fileTypeFilter(fileType, file.getName())) {
                continue;
            }
            // 根据最后修改时间过滤
            List<String> lastModifiedRange = fileMatchCondition.getLastModifiedRange();
            if (!CollectionUtils.isEmpty(lastModifiedRange) && !lastModifiedFilter(lastModifiedRange, file.lastModified())) {
                continue;
            }
            String keyWords4F = fileMatchCondition.getFileNameMatchCondition().getKeyWords();
            // 根据文件名过滤
            if (!StringUtils.isEmpty(keyWords4F) && !fileNameFilter(fileMatchCondition.getFileNameMatchCondition(), file.getName())) {
                continue;
            }
            // 根据文件内容过滤
            String keyWords4C = fileMatchCondition.getContentMatchCondition().getKeyWords();
            if (!StringUtils.isEmpty(keyWords4C) && !contentFilter(fileMatchCondition.getContentMatchCondition(), file)) {
                continue;
            }
            list.add(file.getAbsolutePath());
        }
        long end = System.currentTimeMillis();
        long time = (end - start) / 1000;
        String msg = "查找了 " + allFiles.size() + " 个文件," + "找到了 " + list.size() + " 个文件,耗时 " + time + " s";
        return MyResponse.success(list).setMessage(msg);
    }

    private List<File> getAllFiles(String directories) {
        List<File> allFiles = new ArrayList<>();
        directories = directories.replace("；", ";");
        for (String directory : directories.split(";")) {
            List<File> fileList = new ArrayList<>();
            FileUtils.getFiles(new File(directory), fileList);
            allFiles.addAll(fileList);
        }
        return allFiles;
    }

    private Boolean fileTypeFilter(String fileType, String fileName) {
        return fileName.endsWith(fileType);
    }

    private Boolean lastModifiedFilter(List<String> lastModifiedRange, long lastModified) throws ParseException {
        long startTime = new SimpleDateFormat("yyyy-MM-dd").parse(lastModifiedRange.get(0)).getTime();
        long endTime = new SimpleDateFormat("yyyy-MM-dd").parse(lastModifiedRange.get(1)).getTime();
        return lastModified >= startTime && lastModified <= endTime;
    }

    private Boolean fileNameFilter(StringMatchCondition fileNameMatchCondition, String fileName) {
        String keyWords = fileNameMatchCondition.getKeyWords();
        keyWords = keyWords.replace("；", ";").trim();
        int lastPoint = fileName.lastIndexOf(".");
        String name = fileName.substring(0, lastPoint);
        String suffix = fileName.substring( lastPoint);
        for (String keyWord : keyWords.split(";")) {
            if (keyWord.endsWith(suffix)) {
                keyWord = keyWord.substring(0,keyWord.length()-suffix.length());
            }
            fileNameMatchCondition.setKeyWord(keyWord);
            Boolean keyWordMatchResult = stringNameFilter(fileNameMatchCondition, name);
            if ("1".equals(fileNameMatchCondition.getRelationship()) && !keyWordMatchResult) {
                return false;
            }
            if ("2".equals(fileNameMatchCondition.getRelationship()) && keyWordMatchResult) {
                return true;
            }
        }
        return "1".equals(fileNameMatchCondition.getRelationship());
    }

    private Boolean contentFilter(StringMatchCondition contentMatchCondition, File file) throws IOException {
        String fileName = file.getName();
        String fileType = fileName.substring(fileName.lastIndexOf(".") + 1);
        // 只有文本文件才搜索内容
        if (!TEXT_FILE.contains(fileType)) {
            return false;
        }
        List<String> lines = FileUtils.readFileByLine(file);
        String keyWords = contentMatchCondition.getKeyWords();
        keyWords = keyWords.trim().replace("；", ";");
        String content = String.join("\n", lines);
        String[] keyWordArray = keyWords.split(";");
        for (String keyWord : keyWordArray) {
//            System.out.println("正在从 "+file.getName()+" 中寻找 "+ keyWord);
            contentMatchCondition.setKeyWord(keyWord);
            Boolean keyWordMatchResult = stringNameFilter(contentMatchCondition, content);
            if ("1".equals(contentMatchCondition.getRelationship()) && !keyWordMatchResult) {
                return false;
            }
            if ("2".equals(contentMatchCondition.getRelationship()) && keyWordMatchResult) {
                return true;
            }
        }
        return "1".equals(contentMatchCondition.getRelationship());
    }

    private Boolean stringNameFilter(StringMatchCondition stringMatchCondition, String str) {
        String keyWord = stringMatchCondition.getKeyWord();
        if (stringMatchCondition.getIgnoreCase()) {
            str = str.toLowerCase();
            keyWord = keyWord.toLowerCase();
        }
        if (stringMatchCondition.getRegex() && str.matches(keyWord)) {
            return true;
        }
        if (stringMatchCondition.getEquals() && str.equals(keyWord)) {
            return true;
        }
        if (stringMatchCondition.getStartsWith() && str.startsWith(keyWord)) {
            return true;
        }
        if (stringMatchCondition.getContains() && str.contains(keyWord)) {
            return true;
        }
        if (stringMatchCondition.getEndsWith()) {
            int suffix = str.lastIndexOf(".");
            return str.substring(0, suffix).endsWith(keyWord);
        }
        return false;
    }

}
